﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
using System.Management;
using Microsoft.Win32;
using System.Xml;

namespace BuildAndDeployTool
{
    public partial class BuildAndDeploy : Form
    {

        public BuildAndDeploy()
        {
            InitializeComponent();


            grdProjects.DataSource = BindGrid();

            grdProjects.Columns[0].Width = 200;
            grdProjects.Columns[3].Visible = false;

            cmbEnv.Items.Add("Local");
            cmbEnv.Items.Add("Test");
            cmbEnv.Items.Add("UAT");
            cmbEnv.Items.Add("Prod");

            cmbEnv.SelectedItem = "Local";

            cmbDeplType.Items.Add("Deploy");
            cmbDeplType.Items.Add("UnDeploy");
            cmbDeplType.SelectedItem = "Deploy";

            Control.CheckForIllegalCrossThreadCalls = false;


        }

        public DataTable BindGrid()
        {
            DataTable projects = new DataTable();

            DataColumn projectName = new DataColumn("ProjectName", typeof(string));
            DataColumn required = new DataColumn("Required", typeof(bool));
            DataColumn version = new DataColumn("Version", typeof(string));
            DataColumn order = new DataColumn("Order", typeof(int));

            projects.Columns.Add(projectName);
            projects.Columns.Add(version);
            projects.Columns.Add(required);
            projects.Columns.Add(order);

            CreateProject(projects, "GoldProcess.Common", false, "2.1.5.3552", 1);
            CreateProject(projects, "GoldProcess.Clearing", false, "2.1.5.3552", 3);
            CreateProject(projects, "GoldProcess.LDN", false, "2.1.5.3552", 4);
            


            return projects;

        }

        public void CreateProject(DataTable dt, string projectName, bool required, string version, int order)
        {
            DataRow project = dt.NewRow();
            project["ProjectName"] = projectName;
            project["Required"] = required;
            project["Version"] = version;
            project["Order"] = order;

            dt.Rows.Add(project);
        }

        /*public void CreateProject(DataTable dt, string projectName, string version, bool required)
        {
            DataRow project = dt.NewRow();
            project["ProjectName"] = projectName;
            project["Required"] = required;
            project["Version"] = version;

            dt.Rows.Add(project);
        }*/

        private void btnBuild_Click(object sender, EventArgs e)
        {
            lblPrjName.Text = string.Empty;
            prgBar.Value = 0;
            bgw.DoWork += new DoWorkEventHandler(bgw_DoWork);

            if (txtBuildLocation.Text.Length == 0)
                errPrv.SetError(txtBuildLocation, "Build Location is empty");
            else
            {
                errPrv.SetError(txtBuildLocation, "");
                bgw.RunWorkerAsync();
            }

        }

        void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            ((BackgroundWorker)sender).Dispose();
        }

        void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            prgBar.Value = e.ProgressPercentage;
            //int percent = (int)(((double)prgBar.Value / (double)prgBar.Maximum) * 100);
            //prgBar.CreateGraphics().DrawString(prgBar.Value.ToString() + "%", new Font("Arial", (float)8.25, FontStyle.Bold), Brushes.Black, new PointF(prgBar.Width / 2 - 10, prgBar.Height / 2 - 7)); 
        }

        private void BuildProjects()
        {
            StreamWriter writer;


            int total = 0;
            int counter = 0;

            foreach (DataGridViewRow row in grdProjects.Rows)
            {

                if (row.Cells["Required"].Value == null)
                    break;
                if ((bool)row.Cells["Required"].Value == true)
                {
                    total++;
                }
            }

            foreach (DataGridViewRow row in grdProjects.Rows)
            {

                if (row.Cells[2].Value == null)
                    break;
                if ((bool)row.Cells[2].Value == true)
                {
                    writer = new StreamWriter(@"c:\temp\buildproject.bat");
                    StringBuilder script = new StringBuilder();

                    script.AppendLine("@SETLOCAL");
                    script.AppendLine(@"CALL ""%VS80COMNTOOLS%vsvars32.bat""");

                    script.AppendLine(@"cd " + txtBuildLocation.Text + @"\BizTalk\" + row.Cells["ProjectName"].Value);
                    script.AppendLine("devenv " + row.Cells["ProjectName"].Value + ".sln /Build");
                    script.AppendLine(@"cd " + txtBuildLocation.Text + @"\BizTalk\" + row.Cells["ProjectName"].Value + @"\" + row.Cells["ProjectName"].Value + @".Deployment");
                    script.AppendLine(@"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe /p:Configuration=Debug /p:ProductVersion=" + row.Cells["Version"].Value + " /p:ProjectVersion=" + row.Cells["Version"].Value + @" /t:Installer " + row.Cells["ProjectName"].Value + ".Deployment.btdfproj");
                    script.AppendLine(@"xcopy """ + txtBuildLocation.Text + @"\BizTalk\" + row.Cells["ProjectName"].Value + @"\" + row.Cells["ProjectName"].Value + @".Deployment\bin\debug\*.*"" """ + txtBuildLocation.Text + @"\Build Products\" + row.Cells["ProjectName"].Value + @"\*.*"" /Y");
                    script.AppendLine(@"""C:\Program Files\Deployment Framework for BizTalk\5.0\Framework\DeployTools\EnvironmentSettingsExporter.exe"" """ + txtBuildLocation.Text + @"\" + @"\BizTalk\" + row.Cells["ProjectName"].Value + @"\" + row.Cells["ProjectName"].Value + @".Deployment\EnvironmentSettings\SettingsFileGenerator.xml"" ""..\..\..\Build Products\" + row.Cells["ProjectName"].Value + @"""");


                    writer.Write(script.ToString());
                    writer.Flush();
                    writer.Dispose();

                    ProcessStartInfo startInfo = new ProcessStartInfo();
                    startInfo.FileName = "c:\\temp\\buildproject.bat";
                    startInfo.CreateNoWindow = false;
                    startInfo.UseShellExecute = false;


                    Process process = new Process();
                    process.EnableRaisingEvents = true;
                    process.StartInfo = startInfo;
                    process.Start();



                    while (true)
                    {
                        if (!process.HasExited)
                        {
                            lblPrjName.Text = "Building  " + row.Cells["ProjectName"].Value.ToString();
                        }
                        else
                        {
                            lblPrjName.Text = "Completed  " + row.Cells["ProjectName"].Value.ToString();
                            break;
                        }
                    }

                    counter++;

                    int percents = (counter * 100) / total;
                    bgw.ReportProgress(percents, counter);

                }
            }
        }

        void bgw_DoWork(object sender, DoWorkEventArgs e)
        {
            bgw = new BackgroundWorker();
            bgw.ProgressChanged += new ProgressChangedEventHandler(bgw_ProgressChanged);
            bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);
            bgw.WorkerReportsProgress = true;
            BuildProjects();
        }

        DataTable BindGridForDeploy()
        {
            DataTable projects = new DataTable();

            DataColumn projectName = new DataColumn("ProjectName", typeof(string));
            DataColumn version = new DataColumn("Version", typeof(string));
            DataColumn required = new DataColumn("Required", typeof(bool));
            DataColumn order = new DataColumn("Order", typeof(int));

            projects.Columns.Add(projectName);
            projects.Columns.Add(version);
            projects.Columns.Add(required);
            projects.Columns.Add(order);

            if (grdDeployProjects.DataSource == null)
            {
                CreateProject(projects, "GoldProcess.Common", false, "2.1.5.3552", 1);
                CreateProject(projects, "PaymentGW.MT940.Common", false, "2.1.5.3552", 2);
                CreateProject(projects, "GoldProcess.Clearing", false, "2.1.5.3552", 3);
                CreateProject(projects, "GoldProcess.LDN", false, "2.1.5.3552", 4);
            }
            else
            {
                DataTable originalSet = (DataTable)grdDeployProjects.DataSource;

                DataView dv = originalSet.DefaultView;
                dv.Sort = "Order";
                projects = dv.ToTable();



            }





            return projects;
        }

        DataTable BindGridForUnDeploy()
        {
            DataTable projects = new DataTable();

            DataColumn projectName = new DataColumn("ProjectName", typeof(string));
            DataColumn version = new DataColumn("Version", typeof(string));
            DataColumn required = new DataColumn("Required", typeof(bool));
            DataColumn order = new DataColumn("Order", typeof(int));

            projects.Columns.Add(projectName);
            projects.Columns.Add(version);
            projects.Columns.Add(required);

            if (grdDeployProjects.DataSource == null)
            {
                CreateProject(projects, "GoldProcess.Common", false, "2.1.5.3552", 1);
                CreateProject(projects, "PaymentGW.MT940.Common", false, "2.1.5.3552", 2);
                CreateProject(projects, "GoldProcess.Clearing", false, "2.1.5.3552", 3);
                CreateProject(projects, "GoldProcess.LDN", false, "2.1.5.3552", 4);

                DataView dv = projects.DefaultView;
                dv.Sort = "Order DESC";
                projects = dv.ToTable();
            }
            else
            {
                DataTable originalSet = (DataTable)grdDeployProjects.DataSource;

                DataView dv = originalSet.DefaultView;
                dv.Sort = "Order DESC";
                projects = dv.ToTable();
            }


            return projects;
        }

        private void btnDeploy_Click(object sender, EventArgs e)
        {
            lblDeployStatus.Text = string.Empty;
            pgDeployBar.Value = 0;

            bgwDeploy.DoWork += new DoWorkEventHandler(bgwDeploy_DoWork);

            if (txtBuildLocation.Text.Length == 0)
                errPrv.SetError(txtBuildLocation, "Build Location is empty");
            else
            {
                errPrv.SetError(txtBuildLocation, "");
                bgwDeploy.RunWorkerAsync();
            }
        }

        void bgwDeploy_DoWork(object sender, DoWorkEventArgs e)
        {
            bgwDeploy = new BackgroundWorker();
            bgwDeploy.ProgressChanged += new ProgressChangedEventHandler(bgwDeploy_ProgressChanged);
            bgwDeploy.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgwDeploy_RunWorkerCompleted);
            bgwDeploy.WorkerReportsProgress = true;
            DeployProjects();
        }

        private void DeployProjects()
        {
            StreamWriter writer;


            int total = 0;
            int counter = 0;

            foreach (DataGridViewRow row in grdDeployProjects.Rows)
            {

                if (row.Cells["Required"].Value == null)
                    break;
                if ((bool)row.Cells["Required"].Value == true)
                {
                    total++;
                }
            }

            foreach (DataGridViewRow row in grdDeployProjects.Rows)
            {
                if (row.Cells["Required"].Value == null)
                    break;
                if ((bool)row.Cells["Required"].Value == true)
                {


                    if (cmbDeplType.SelectedItem.ToString() == "Deploy")
                    {

                        string logFilename = txtBuildLocation.Text + @"\" + row.Cells["ProjectName"].Value.ToString() + @"\" + row.Cells["ProjectName"].Value.ToString() + "-" + DateTime.Now.ToString("yyyyMMdd");
                        string environmentSettings = txtBuildLocation.Text + @"\" + row.Cells["ProjectName"].Value.ToString() + @"\" + "Exported_" + cmbEnv.SelectedItem.ToString() + "Settings.xml";

                        // Installation logic
                        writer = new StreamWriter(@"c:\temp\installproject.bat");
                        StringBuilder script = new StringBuilder();
                        script.AppendLine(@"cd " + txtBuildLocation.Text + @"\" + row.Cells["ProjectName"].Value);
                        script.AppendLine("msiexec -i " + row.Cells["ProjectName"].Value + "-" + row.Cells["Version"].Value + @".msi /passive  /liv """ + logFilename + @".Install.log"" INSTALLDIR=""c:\Program Files\BTMU\" + row.Cells["ProjectName"].Value + @"""");

                        writer.Write(script.ToString());
                        writer.Flush();
                        writer.Dispose();

                        ProcessStartInfo startInfo = new ProcessStartInfo();
                        startInfo.FileName = "c:\\temp\\installproject.bat";
                        startInfo.CreateNoWindow = false;
                        startInfo.UseShellExecute = false;


                        Process process = new Process();
                        process.EnableRaisingEvents = true;
                        process.StartInfo = startInfo;
                        process.Start();

                        while (true)
                        {
                            if (!process.HasExited)
                            {
                                lblDeployStatus.Text = "Installing  " + row.Cells["ProjectName"].Value.ToString();
                            }
                            else
                            {
                                lblDeployStatus.Text = "Completed Installing " + row.Cells["ProjectName"].Value.ToString();
                                break;
                            }
                        }

                        // Deployment logic
                        writer = new StreamWriter(@"c:\temp\deployproject.bat");
                        script = new StringBuilder();
                        script.AppendLine(@"""C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe"" /p:DeployBizTalkMgmtDB=true;Configuration=Server;SkipUndeploy=false;ENV_SETTINGS=""" + environmentSettings + @""";BT_DEPLOY_MGMT_DB=true /l:FileLogger,Microsoft.Build.Engine;logfile=""" + logFilename + ".Deploy.log" + @""" ""C:\Program Files\BTMU\" + row.Cells["ProjectName"].Value + @"\Deployment\" + row.Cells["ProjectName"].Value + @".Deployment.btdfproj""");
                        //"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe" /p:DeployBizTalkMgmtDB=true;Configuration=Server;SkipUndeploy=false;ENV_SETTINGS="C:\Subversion\PaymentGW\branches\2.1 11IN044 SEDM P1\src\Build Products\PaymentGW.Common\Exported_LocalSettings.xml";BT_DEPLOY_MGMT_DB=true /l:FileLogger,Microsoft.Build.Engine;logfile="C:\Subversion\PaymentGW\branches\2.1 11IN044 SEDM P1\src\Build Products\PaymentGW.Common\PaymentGW.Common-20120907.Deploy.log" "C:\Program Files\BTMU\PaymentGW.Common\Deployment\PaymentGW.Common.Deployment.btdfproj"

                        writer.Write(script.ToString());
                        writer.Flush();
                        writer.Dispose();

                        startInfo = new ProcessStartInfo();
                        startInfo.FileName = "c:\\temp\\deployproject.bat";
                        startInfo.CreateNoWindow = false;
                        startInfo.UseShellExecute = false;


                        process = new Process();
                        process.EnableRaisingEvents = true;
                        process.StartInfo = startInfo;
                        process.Start();

                        while (true)
                        {
                            if (!process.HasExited)
                            {
                                lblDeployStatus.Text = "Deploying  " + row.Cells["ProjectName"].Value.ToString();
                            }
                            else
                            {
                                lblDeployStatus.Text = "Completed Deploying " + row.Cells["ProjectName"].Value.ToString();
                                break;
                            }
                        }

                        counter++;

                        int percents = (counter * 100) / total;
                        bgwDeploy.ReportProgress(percents, counter);
                    }
                    else if (cmbDeplType.SelectedItem.ToString() == "UnDeploy")
                    {

                        string logFilename = txtBuildLocation.Text + @"\" + row.Cells["ProjectName"].Value.ToString() + @"\" + row.Cells["ProjectName"].Value.ToString() + "-" + DateTime.Now.ToString("yyyyMMdd");
                        string environmentSettings = @"C:\Program Files\BTMU\" + row.Cells["ProjectName"].Value.ToString() + @"\Deployment\EnvironmentSettings\" + "Exported_" + cmbEnv.SelectedItem.ToString() + "Settings.xml";

                        RegistryKey rootkey = Registry.LocalMachine;
                        string productId = RetrieveProductIdForProducts(row.Cells["ProjectName"].Value.ToString());
                        RegistryKey subkey = rootkey.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + productId);

                        //RegistryValueKind valKind = subkey.GetValueKind("DisplayVersion");
                        string version = subkey.GetValue("DisplayVersion").ToString();

                        // Undeploy logic
                        writer = new StreamWriter(@"c:\temp\undeployproject.bat");
                        StringBuilder script = new StringBuilder();
                        script.AppendLine(@"""C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe"" /p:DeployBizTalkMgmtDB=true;Configuration=Server;SkipUndeploy=false;ENV_SETTINGS=""" + environmentSettings + @""";PreRequisites=false;BT_DEPLOY_MGMT_DB=true /target:Undeploy /l:FileLogger,Microsoft.Build.Engine;logfile=""" + logFilename + ".UnDeploy.log" + @""" ""C:\Program Files\BTMU\" + row.Cells["ProjectName"].Value + @"\Deployment\" + row.Cells["ProjectName"].Value + @".Deployment.btdfproj""");

                        writer.Write(script.ToString());
                        writer.Flush();
                        writer.Dispose();

                        ProcessStartInfo startInfo = new ProcessStartInfo();
                        startInfo.FileName = "c:\\temp\\undeployproject.bat";
                        startInfo.CreateNoWindow = false;
                        startInfo.UseShellExecute = false;


                        Process process = new Process();
                        process.EnableRaisingEvents = true;
                        process.StartInfo = startInfo;
                        process.Start();

                        while (true)
                        {
                            if (!process.HasExited)
                            {
                                lblDeployStatus.Text = "Undeploying  " + row.Cells["ProjectName"].Value.ToString();
                            }
                            else
                            {
                                lblDeployStatus.Text = "Completed Undeploying" + row.Cells["ProjectName"].Value.ToString();
                                break;
                            }
                        }

                        // Uninstall logic
                        writer = new StreamWriter(@"c:\temp\uninstallproject.bat");
                        script = new StringBuilder();

                        script.AppendLine(@"cd " + txtBuildLocation.Text + @"\" + row.Cells["ProjectName"].Value);
                        script.AppendLine("msiexec /uninstall " + row.Cells["ProjectName"].Value + "-" + version + @".msi /passive  /liv """ + logFilename + @".UnInstall.log"" ");

                        writer.Write(script.ToString());
                        writer.Flush();
                        writer.Dispose();

                        startInfo = new ProcessStartInfo();
                        startInfo.FileName = "c:\\temp\\uninstallproject.bat";
                        startInfo.CreateNoWindow = false;
                        startInfo.UseShellExecute = false;


                        process = new Process();
                        process.EnableRaisingEvents = true;
                        process.StartInfo = startInfo;
                        process.Start();

                        while (true)
                        {
                            if (!process.HasExited)
                            {
                                lblDeployStatus.Text = "Uninstalling  " + row.Cells["ProjectName"].Value.ToString();
                            }
                            else
                            {
                                lblDeployStatus.Text = "Completed Uninstalling " + row.Cells["ProjectName"].Value.ToString();
                                break;
                            }
                        }

                        counter++;

                        int percents = (counter * 100) / total;
                        bgwDeploy.ReportProgress(percents, counter);
                    }
                }
            }
        }

        void bgwDeploy_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            ((BackgroundWorker)sender).Dispose();
        }

        void bgwDeploy_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            pgDeployBar.Value = e.ProgressPercentage;
        }

        string RetrieveProductIdForProducts(string productName)
        {
            string productId = string.Empty;
            if (productName == "GoldProcess.Common")
                productId = "{8678e66e-702d-4a02-9eaf-b3f9b7c473be}";
            if (productName == "GoldProcess.Clearing")
                productId = "{d4cd11b7-4784-4799-a0f4-f63fee640014}";
            if (productName == "GoldProcss.LDN")
                productId = "{653bab91-e8a5-4e40-8fb2-6c2e79fa22ea}";
            
            return productId;
        }

        private void cmbDeplType_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cmbDeplType.SelectedItem.ToString() == "Deploy")
            {
                grdDeployProjects.DataSource = BindGridForDeploy();
            }
            else
            {
                grdDeployProjects.DataSource = BindGridForUnDeploy();
            }

            grdDeployProjects.Columns[0].Width = 200;
            grdDeployProjects.Columns[3].Visible = false;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (txtVersion.Text.Length == 0)
                errPrv.SetError(txtVersion, "Version is empty. Provide a valid version number");
            else
            {
                errPrv.SetError(txtVersion, "");
                foreach (DataGridViewRow row in grdProjects.Rows)
                {
                    if (row.Cells["Required"].Value == null)
                        break;
                    if ((bool)row.Cells["Required"].Value == true)
                    {
                        row.Cells["Version"].Value = txtVersion.Text;
                    }
                }
            }
        }

        private void btnExport_Click(object sender, EventArgs e)
        {
            DataTable dt = new DataTable("BuildManifest");

            DataColumn projectName = new DataColumn("ProjectName", typeof(string));
            DataColumn version = new DataColumn("Version", typeof(string));
            DataColumn required = new DataColumn("Required", typeof(string));
            DataColumn order = new DataColumn("Order", typeof(string));

            dt.Columns.Add(projectName);
            dt.Columns.Add(version);
            dt.Columns.Add(required);
            dt.Columns.Add(order);

            foreach (DataGridViewRow row in grdProjects.Rows)
            {
                if (row.Cells["Required"].Value == null)
                    break;
                int icols = grdProjects.Columns.Count;

                if ((bool)row.Cells["Required"].Value == true)
                {
                    DataRow newRow = dt.NewRow();

                    for (int i = 0; i < icols; i++)
                    {
                        newRow[i] = row.Cells[i].Value;
                    }

                    dt.Rows.Add(newRow);
                }
            }

            dt.WriteXml(@"c:\temp\buildmanifest.xml");


        }

        private void btnImport_Click(object sender, EventArgs e)
        {
            if (txtManifest.Text.Length == 0)
                errPrv.SetError(txtManifest, "Manifest file location can't be empty");
            else
            {
                errPrv.SetError(txtManifest, "");

                DataTable projects = new DataTable();
                DataColumn projectName = new DataColumn("ProjectName", typeof(string));
                DataColumn version = new DataColumn("Version", typeof(string));
                DataColumn required = new DataColumn("Required", typeof(bool));
                DataColumn order = new DataColumn("Order", typeof(int));

                projects.Columns.Add(projectName);
                projects.Columns.Add(version);
                projects.Columns.Add(required);
                projects.Columns.Add(order);


                XmlDocument doc = new XmlDocument();
                doc.Load(txtManifest.Text);

                foreach (XmlNode node in doc.SelectNodes("//BuildManifest"))
                {
                    DataRow newRow = projects.NewRow();
                    newRow[0] = node["ProjectName"].InnerText;
                    newRow[1] = node["Version"].InnerText;
                    newRow[2] = node["Required"].InnerText;
                    newRow[3] = node["Order"].InnerText;
                    projects.Rows.Add(newRow);
                }

                DataView dv = projects.DefaultView;
                dv.Sort = "Order DESC";
                projects = dv.ToTable();

                grdDeployProjects.DataSource = projects;
                grdDeployProjects.Columns[3].Visible = false;

                cmbDeplType.SelectedItem = "Undeploy";


            }
        }

    }
}